﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web.Services.Protocols;
using System.Xml;
using Aquasoft.Iszr.Proxy.Properties;

namespace Aquasoft.Iszr.Proxy.WebServices
{

    public abstract class IszrServiceBase : SoapHttpClientProtocol, IIszrMessageInterceptor
    {
        protected override WebResponse GetWebResponse(WebRequest request)
        {
            return IszrMessageInterceptor.Instance.OnGetWebResponse(this, request);
        }

        protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
        {
            return IszrMessageInterceptor.Instance.OnGetWebResponseAsync(this, request, result);
        }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            return IszrMessageInterceptor.Instance.OnGetWebRequest(this, uri);
        }

        protected override XmlWriter GetWriterForMessage(SoapClientMessage message, int bufferSize)
        {
            return IszrMessageInterceptor.Instance.OnGetWriterForMessage(this, message, bufferSize);
        }

        protected override XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize)
        {
            return IszrMessageInterceptor.Instance.OnGetReaderForMessage(this, message, bufferSize);
        }

        #region IIszrMessageInterceptor implementation (default implementation)
        WebResponse IIszrMessageInterceptor.GetWebResponse(IszrServiceBase service, WebRequest request)
        {
            return base.GetWebResponse(request);
        }

        WebResponse IIszrMessageInterceptor.GetWebResponseAsync(IszrServiceBase service, WebRequest request, IAsyncResult result)
        {
            return base.GetWebResponse(request, result);
        }

        WebRequest IIszrMessageInterceptor.GetWebRequest(IszrServiceBase service, Uri uri)
        {
            var result = (HttpWebRequest)base.GetWebRequest(uri);
            result.KeepAlive = true;
            return result;
        }

        XmlReader IIszrMessageInterceptor.GetReaderForMessage(IszrServiceBase service, SoapClientMessage message, int bufferSize)
        {
            return base.GetReaderForMessage(message, bufferSize);
        }

        XmlWriter IIszrMessageInterceptor.GetWriterForMessage(IszrServiceBase service, SoapClientMessage message, int bufferSize)
        {
            return base.GetWriterForMessage(message, bufferSize);
        }

        #endregion    
    }

    public abstract class IszrService<TI, TO> : IszrServiceBase
        where TI : class, new()
        where TO : class, new()
    {
        protected IszrService()
        {
            SetupService();    
        }

        protected abstract TO InvokeService(TI input);

        public TO CallService(TI input)
        {
            TO result;
            IszrServiceManager.Instance.OnBeforeCallService(this, input);
            try
            {
                result = InvokeService(input);
            }
            catch (Exception e)
            {
                IszrServiceManager.Instance.OnErrorCallService(this, input, e);                    
                throw;
            }
            IszrServiceManager.Instance.OnAfterCallService(this, input, result);
            return result;
        }

        private void SetupService()
        {
            IszrServiceManager.Instance.OnServiceCreated(this);
        }
    }
}
